/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package me.panpf.sketch.sample.widget;

import me.panpf.sketch.Gif;
import me.panpf.sketch.SketchImageView;
import me.panpf.sketch.datasource.DataSource;
import me.panpf.sketch.decode.ImageOrientationCorrector;
import me.panpf.sketch.decode.NotFoundGifLibraryException;
import me.panpf.sketch.drawable.SketchDrawable;
import me.panpf.sketch.drawable.SketchLoadingDrawable;
import me.panpf.sketch.drawable.SketchShapeBitmapDrawable;
import me.panpf.sketch.request.DisplayOptions;
import me.panpf.sketch.request.RedisplayListener;
import me.panpf.sketch.request.Resize;
import me.panpf.sketch.sample.AppConfig;
import me.panpf.sketch.sample.ImageOptions;
import me.panpf.sketch.sample.ResourceTable;
import me.panpf.sketch.sample.event.Events;
import me.panpf.sketch.sample.util.FileUtils;
import me.panpf.sketch.uri.GetDataSourceException;
import me.panpf.sketch.uri.UriModel;
import me.panpf.sketch.util.Log;
import me.panpf.sketch.util.SketchUtils;
import me.panpf.sketch.zoom.Size;
import ohos.aafwk.ability.Ability;
import ohos.agp.components.*;
import ohos.agp.components.element.Element;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.IDialog;
import ohos.agp.window.service.Window;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.PixelMap;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.EventBusException;
import org.greenrobot.eventbus.Subscribe;

import java.io.IOException;

/**
 * SampleImageView
 */
public class SampleImageView extends SketchImageView {
    private Page page = null;
    private boolean disabledRedisplay = false;
    private LongClickShowDrawableInfoListener longClickShowDrawableInfoListener = new LongClickShowDrawableInfoListener();
    private Context context;
    private String huanHang = "";

    public SampleImageView(Context context) {
        super(context);
        this.context = context;
        init();
    }

    /**
     * setPage
     * @param page
     */
    public void setPage(Page page) {
        this.page = page;
    }

    public SampleImageView(Context context, AttrSet attrs) throws NotExistException, WrongTypeException, IOException {
        super(context, attrs);
        this.context = context;
        init();
    }

    public SampleImageView(Context context, AttrSet attrs, int defStyle) throws NotExistException, WrongTypeException, IOException {
        this(context, attrs);
    }

    private void init() {
        huanHang = context.getString(ResourceTable.String_huanhang);
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.LONG_CLICK_SHOW_IMAGE_INFO));
    }

    @Override
    public void onComponentBoundToWindow(Component component) {
        super.onComponentBoundToWindow(component);
        try {
            EventBus.getDefault().register(this);
        } catch (EventBusException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onReadyDisplay(UriModel uriModel) {
        super.onReadyDisplay(uriModel);

        disabledRedisplay = true;
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.SHOW_GIF_FLAG));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.SHOW_IMAGE_FROM_FLAG));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.CLICK_SHOW_PRESSED_STATUS));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.SHOW_IMAGE_DOWNLOAD_PROGRESS));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.CLICK_RETRY_ON_PAUSE_DOWNLOAD));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.CLICK_RETRY_ON_FAILED));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.CLICK_PLAY_GIF));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.DISABLE_CORRECT_IMAGE_ORIENTATION));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.PLAY_GIF_ON_LIST));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.THUMBNAIL_MODE));
        onEvent(new Events.AppConfigChangedEvent(AppConfig.Key.CACHE_PROCESSED_IMAGE));
        disabledRedisplay = false;
    }

    /**
     * setOptions
     *
     * @param optionsId
     */
    public void setOptions(ImageOptions.Type optionsId) {
        setOptions(ImageOptions.getDisplayOptions(getContext(), optionsId));
    }

    @Override
    public boolean redisplay(RedisplayListener listener) {
        return !disabledRedisplay && super.redisplay(listener);
    }

    @Subscribe
    public void onEvent(Events.AppConfigChangedEvent event) {
        switch (event.key) {
            case SHOW_GIF_FLAG:
            case CLICK_SHOW_PRESSED_STATUS:
            case SHOW_IMAGE_DOWNLOAD_PROGRESS:
            case CLICK_RETRY_ON_PAUSE_DOWNLOAD:
            case CLICK_RETRY_ON_FAILED:
            case CLICK_PLAY_GIF:
                setShowImageAction(event.key);
                break;
            case SHOW_IMAGE_FROM_FLAG:
                setShowImageFromEnabled(AppConfig.getBoolean(getContext(), event.key));
                break;
            case MOBILE_NETWORK_PAUSE_DOWNLOAD:
            case GLOBAL_DISABLE_CACHE_IN_DISK:
            case GLOBAL_DISABLE_BITMAP_POOL:
            case GLOBAL_DISABLE_CACHE_IN_MEMORY:
                redisplay(null);
                break;
            case DISABLE_CORRECT_IMAGE_ORIENTATION: {
                boolean correctImageOrientationDisabled = AppConfig.getBoolean(getContext(), event.key);
                getOptions().setCorrectImageOrientationDisabled(correctImageOrientationDisabled);
                redisplay((cacheUri, cacheOptions) -> cacheOptions.setCorrectImageOrientationDisabled(correctImageOrientationDisabled));
                break;
            }
            case THUMBNAIL_MODE:
                setThumbnailMode(event.key);
                break;
            case CACHE_PROCESSED_IMAGE: {
                boolean cacheProcessedImageInDisk = AppConfig.getBoolean(getContext(), event.key);
                getOptions().setCacheProcessedImageInDisk(cacheProcessedImageInDisk);
                redisplay((cacheUri, cacheOptions) -> cacheOptions.setCacheProcessedImageInDisk(cacheProcessedImageInDisk));
                break;
            }
            case LONG_CLICK_SHOW_IMAGE_INFO: {
                setLongClickListener((AppConfig.getBoolean(getContext(), AppConfig.Key.LONG_CLICK_SHOW_IMAGE_INFO)) ? longClickShowDrawableInfoListener : null);
                break;
            }
            default: {
                break;
            }
        }
    }

    private void setThumbnailMode(AppConfig.Key key) {
        if (page == Page.PHOTO_LIST) {
            boolean thumbnailMode = AppConfig.getBoolean(getContext(), key);
            getOptions().setThumbnailMode(thumbnailMode).setResize(thumbnailMode ? Resize.byViewFixedSize() : null);
            redisplay((cacheUri, cacheOptions) -> {
                cacheOptions.setThumbnailMode(thumbnailMode);
                cacheOptions.setResize(thumbnailMode ? Resize.byViewFixedSize() : null);
            });
        }
    }

    private void setShowImageAction(AppConfig.Key key) {
        switch (key) {
            case SHOW_GIF_FLAG:
                if (page == Page.PHOTO_LIST || page == Page.SEARCH_LIST || page == Page.UNSPLASH_LIST || page == Page.APP_LIST) {
                    setShowGifFlagEnabled((AppConfig.getBoolean(getContext(), AppConfig.Key.SHOW_GIF_FLAG)) ? ResourceTable.Media_ic_gif : 0);
                }
                break;
            case CLICK_SHOW_PRESSED_STATUS:
                if (page == Page.PHOTO_LIST || page == Page.SEARCH_LIST || page == Page.UNSPLASH_LIST || page == Page.APP_LIST) {
                    setShowPressedStatusEnabled(AppConfig.getBoolean(getContext(), key));
                }
                break;
            case SHOW_IMAGE_DOWNLOAD_PROGRESS:
                if (page == Page.PHOTO_LIST || page == Page.SEARCH_LIST || page == Page.UNSPLASH_LIST || page == Page.APP_LIST) {
                    setShowDownloadProgressEnabled(AppConfig.getBoolean(getContext(), key));
                }
                break;
            case CLICK_RETRY_ON_PAUSE_DOWNLOAD:
                if (page == Page.PHOTO_LIST || page == Page.SEARCH_LIST || page == Page.UNSPLASH_LIST || page == Page.APP_LIST) {
                    setClickRetryOnPauseDownloadEnabled(AppConfig.getBoolean(getContext(), key));
                }
                break;
            case CLICK_RETRY_ON_FAILED:
                if (page == Page.PHOTO_LIST || page == Page.SEARCH_LIST || page == Page.UNSPLASH_LIST || page == Page.APP_LIST) {
                    setClickRetryOnDisplayErrorEnabled(AppConfig.getBoolean(getContext(), key));
                }
                break;
            case CLICK_PLAY_GIF:
                if (page == Page.PHOTO_LIST || page == Page.SEARCH_LIST || page == Page.UNSPLASH_LIST || page == Page.APP_LIST) {
                    try {
                        setClickPlayGifEnabled((AppConfig.getBoolean(getContext(), key)) ? ResourceTable.Media_icon_start : 0);
                    } catch (Exception e1) {
                        e1.printStackTrace();
                    }
                }
                break;
            default:
                break;
        }
    }

    /**
     * onEvent
     *
     * @param event
     */
    @Subscribe
    public void onEvent(Events.CacheCleanEvent event) {
        redisplay(null);
    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        EventBus.getDefault().unregister(this);
        super.onComponentUnboundFromWindow(component);
    }

    /**
     * showInfo
     *
     * @param ability
     */
    public void showInfo(Ability ability) {
        longClickShowDrawableInfoListener.showInfo(ability);
    }

    public enum Page {
        PHOTO_LIST, UNSPLASH_LIST, SEARCH_LIST, APP_LIST, DETAIL, DEMO
    }

    private class LongClickShowDrawableInfoListener implements Component.LongClickedListener {

        private void showInfo(Ability ability) {
            CommonDialog dialog = new CommonDialog(ability);
            dialog.setAutoClosable(true);
            Element drawable = SketchUtils.getLastDrawable(getDrawable());
            Component component = LayoutScatter.getInstance(ability).parse(ResourceTable.Layout_dialog_button, null, false);
            dialog.setContentCustomComponent(component);
            Text text = (Text) component.findComponentById(ResourceTable.Id_title);
            Button button = (Button) component.findComponentById(ResourceTable.Id_button);
            String imageInfo = null;
            if (drawable instanceof SketchLoadingDrawable) {
                imageInfo = "Image is loading, please wait later";
            } else if (drawable instanceof SketchDrawable) {
                imageInfo = assembleImageInfo(drawable, ((SketchDrawable) drawable));
            } else {
                imageInfo = "Unknown source image";
            }
            text.setText(imageInfo);
            dialog.setSize(AttrHelper.vp2px(320, ability), AttrHelper.vp2px(220, ability));
            button.setText("Cancel");
            button.setClickedListener(new ClickedListener() {

                @Override
                public void onClick(Component component) {
                    dialog.destroy();
                }
            });

            dialog.show();
        }

        private String assembleImageInfo(Element drawable, SketchDrawable sketchDrawable) {
            StringBuilder messageBuilder = new StringBuilder();
            messageBuilder.append(sketchDrawable.getKey());

            UriModel uriModel = UriModel.match(getContext(), sketchDrawable.getUri());
            DataSource dataSource = null;
            if (uriModel != null) {
                try {
                    dataSource = uriModel.getDataSource(getContext(), sketchDrawable.getUri(), null);
                } catch (GetDataSourceException e) {
                    e.printStackTrace();
                }
            }

            long imageLength = 0;
            try {
                imageLength = (dataSource != null) ? dataSource.getLength() : 0;
            } catch (IOException e) {
                e.printStackTrace();
            }

            String needDiskSpace = (imageLength > 0) ? FileUtils.formetFileSize(imageLength) : "Unknown";

            int previewDrawableByteCount = sketchDrawable.getByteCount();
            int pixelByteCount;
            if (drawable instanceof SketchShapeBitmapDrawable) {
                PixelMap bitmap = ((SketchShapeBitmapDrawable) drawable).getBitmapDrawable().getPixelMap();
                pixelByteCount = previewDrawableByteCount / bitmap.getImageInfo().size.width / bitmap.getImageInfo().size.height;
            } else {
                pixelByteCount = previewDrawableByteCount / drawable.getWidth() / drawable.getHeight();
            }
            int originImageByteCount = sketchDrawable.getOriginWidth() * sketchDrawable.getOriginHeight() * pixelByteCount;
            String needMemory = FileUtils.formetFileSize(originImageByteCount);
            String mimeType = sketchDrawable.getMimeType();

            messageBuilder.append(huanHang);
            messageBuilder.append(huanHang);
            messageBuilder.append("Original: ")
                    .append(sketchDrawable.getOriginWidth()).append("x").append(sketchDrawable.getOriginHeight())
                    .append("/").append((mimeType != null && mimeType.startsWith("image/")) ? mimeType.substring(6) : "Unknown")
                    .append("/").append(needDiskSpace);
            messageBuilder.append(huanHang);
            messageBuilder.append("                ");
            messageBuilder.append(ImageOrientationCorrector.toName(sketchDrawable.getExifOrientation()))
                    .append("/").append(needMemory);

            messageBuilder.append(huanHang);
            messageBuilder.append(huanHang);
            messageBuilder.append("Preview: ")
                    .append(drawable.getWidth()).append("x").append(drawable.getHeight())
                    .append("/").append(sketchDrawable.getBitmapConfig())
                    .append("/").append(FileUtils.formetFileSize(previewDrawableByteCount));

            return messageBuilder.toString();
        }

        @Override
        public void onLongClicked(Component component) {
            if (component.getContext() instanceof Ability) {
                showInfo((Ability) component.getContext());
            }
        }
    }
}
